package imp

import (
	sqlc "bgs/db/sqlc"
	productGroupGrpc "bgs/grpc/gen/service/product_group"
	"bgs/grpc/gen/shared/message"
	"bytes"
	"context"
	"database/sql"
	"fmt"
)

/****************************************************************************************/
/*                               product_group entity of helper                        */
/****************************************************************************************/

func transformProductGroupEntityToPb(productGroup sqlc.ProductGroup) *productGroupGrpc.ProductGroupEntity {
	return &productGroupGrpc.ProductGroupEntity{
		Id:           productGroup.ID,
		BrandId:      productGroup.BrandID,
		SortNo:       productGroup.SortNo,
		Name:         productGroup.Name,
		ProductCount: productGroup.ProductCount,
	}
}

func mapProductGroupEntityToPb(list []sqlc.ProductGroup, f func(sqlc.ProductGroup) *productGroupGrpc.ProductGroupEntity) []*productGroupGrpc.ProductGroupEntity {
	r := make([]*productGroupGrpc.ProductGroupEntity, len(list))
	for i, item := range list {
		r[i] = f(item)
	}
	return r
}

/****************************************************************************************/
/*                               product_group entity of cmd                            */
/****************************************************************************************/

// UpsertProductGroup 插入/修改商品分组
func (s *ProductAPIService) UpsertProductGroup(ctx context.Context, req *productGroupGrpc.UpsertProductGroupRequest) (res *productGroupGrpc.UpsertProductGroupResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("product_groupImp->UpsertProductGroup:%v", req)
	res = &productGroupGrpc.UpsertProductGroupResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	maxSortNo, err := s.dao.Q.GetProductGroupMaxSortNo(ctx, req.BrandId)
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}

	arg := sqlc.UpsertProductGroupParams{
		BrandID: req.BrandId,
		SortNo:  (maxSortNo + 1),
		Name:    req.Name,
	}

	productGroup, err := s.dao.Q.UpsertProductGroup(ctx, arg)
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	res.ProductGroup = transformProductGroupEntityToPb(productGroup)
	return
}

// UpdateProductGroupName 更新商品分组名称
func (s *ProductAPIService) UpdateProductGroupName(ctx context.Context, req *productGroupGrpc.UpdateProductGroupNameRequest) (res *productGroupGrpc.UpdateProductGroupNameResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("product_groupImp->UpdateProductGroupName:%v", req)
	res = &productGroupGrpc.UpdateProductGroupNameResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	arg := sqlc.UpdateProductGroupNameParams{
		ID:   req.Id,
		Name: req.Name,
	}
	ProductGroup, err := s.dao.Q.UpdateProductGroupName(ctx, arg)
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	res.ProductGroup = transformProductGroupEntityToPb(ProductGroup)
	return
}

// ReorderProductGroups 批量设置商品分组的排序号
func (s *ProductAPIService) ReorderProductGroups(ctx context.Context, req *productGroupGrpc.ReorderProductGroupsRequest) (res *productGroupGrpc.ReorderProductGroupsResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("product_groupImp->ReorderProductGroups:%v", req)
	res = &productGroupGrpc.ReorderProductGroupsResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	var buffer bytes.Buffer
	length := len(req.Ids)
	for idx, id := range req.Ids[:length-1] {
		buffer.WriteString(fmt.Sprintf("(%d,%d),", id, idx+1))
	}
	buffer.WriteString(fmt.Sprintf("(%d,%d)", req.Ids[length-1], length))
	// UPDATE product_groups SET sort_no=a.sort_no FROM (VALUES (1,1),(2,2),(6,3)) AS a (id,sort_no) WHERE product_groups.id=a.id
	updateBatchSQL := fmt.Sprintf("UPDATE product_groups SET sort_no=a.sort_no FROM (VALUES %s) AS a (id,sort_no) WHERE product_groups.id=a.id", buffer.String())

	slog.Infof("updateBatchSQL=>%s", updateBatchSQL)
	err = s.dao.NewTxRunner().StmtExecTx(ctx, updateBatchSQL, func(s *sql.Stmt) (err error) {
		_, err = s.ExecContext(ctx)
		if err != nil {
			return err
		}
		err = s.Close()
		if err != nil {
			return err
		}
		return
	})
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	res.Total = int64(len(req.Ids))
	return

}

// RemoveProductGroup 取消商品分组
func (s *ProductAPIService) RemoveProductGroup(ctx context.Context, req *productGroupGrpc.RemoveProductGroupRequest) (res *productGroupGrpc.RemoveProductGroupResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("product_groupImp->RemoveProductGroup:%v", req)
	res = &productGroupGrpc.RemoveProductGroupResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	var productGroup sqlc.ProductGroup
	productGroupID := req.Id

	err = s.dao.NewTxRunner().SqlcExecTx(ctx, func(q *sqlc.Queries) (err error) {

		err = q.UpdateProductMakeProductGroupIDNullByProductGroupID(ctx, sqlc.NInt64FromInt64(productGroupID))
		if err != nil {
			return err
		}
		slog.Infof("1 将商品的分组id设置未null")

		productGroup, err = q.DisableProductGroup(ctx, productGroupID)
		if err != nil {
			return err
		}
		slog.Info("2 disable product_group ok")

		return
	})
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	res.ProductGroup = transformProductGroupEntityToPb(productGroup)
	return
}

/****************************************************************************************/
/*                            product_group entity of query                            */
/****************************************************************************************/

// GetProductGroup 获取单个商品分组
func (s *ProductAPIService) GetProductGroup(ctx context.Context, req *productGroupGrpc.GetProductGroupRequest) (res *productGroupGrpc.GetProductGroupResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("brand_followImp->GetBrandFollow:%v", req)
	res = &productGroupGrpc.GetProductGroupResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	productGroup, err := s.dao.Q.GetProductGroup(ctx, req.Id)
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	res.ProductGroup = transformProductGroupEntityToPb(productGroup)
	return
}

// ListNormalProductGroupsByBrandID  获取正常的商品分组列表
func (s *ProductAPIService) ListNormalProductGroupsByBrandID(ctx context.Context, req *productGroupGrpc.ListNormalProductGroupsByBrandIDRequest) (res *productGroupGrpc.ListNormalProductGroupsByBrandIDResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("product_groupImp->ListNormalProductGroupsByBrandID:%v", req)

	res = &productGroupGrpc.ListNormalProductGroupsByBrandIDResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	total, err := s.dao.Q.CountNormalProductGroupsByBrandID(ctx, req.BrandId)
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	if total == 0 {
		// 不用继续调用listfunc
		return
	}
	arg := sqlc.ListNormalProductGroupsByBrandIDParams{
		Limit:   req.Limit,
		Offset:  req.Offset,
		BrandID: req.BrandId,
	}
	ProductGroups, err := s.dao.Q.ListNormalProductGroupsByBrandID(ctx, arg)
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	res.Total = total
	res.ProductGroups = mapProductGroupEntityToPb(ProductGroups, transformProductGroupEntityToPb)
	return
}
